package database.common;

import database.ulti.HibernateUtil;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Projections;

public class GenericDao<T, PK extends Serializable> {

    protected SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
    private Class<T> persistentClass;

    @SuppressWarnings("unchecked")
    public GenericDao() {
        Type[] types = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments();
        this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public T add(T newInstance) {
        //getHibernateTemplate().saveOrUpdate(newInstance);
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        session.saveOrUpdate(newInstance);
        session.flush();
        session.getTransaction().commit();
        return newInstance;
    }

    public T getById(PK id) {
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        T result = (T) session.get(persistentClass, id);
        session.flush();
        session.getTransaction().commit();
        return result;
    }

    public T update(T transientObject) {
        //getHibernateTemplate().saveOrUpdate(transientObject);		
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        session.saveOrUpdate(transientObject);
        session.flush();
        session.getTransaction().commit();
        return transientObject;
    }

    public void delete(T persistentObject) {
        //getHibernateTemplate().delete(persistentObject);
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        session.delete(persistentObject);
        session.getTransaction().commit();
    }

    public List<T> getAll() {
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        List<T> list = session.createCriteria(persistentClass).list();
        session.flush();
        session.getTransaction().commit();
        return list;
    }

    @SuppressWarnings("unchecked")
    public List<T> getPage(int start, int count) {
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        List<T> list = session.createCriteria(persistentClass).setMaxResults(count).setFirstResult(start).list();
        session.flush();
        session.getTransaction().commit();
        return list;
    }


    public long count() {
        Session session = sessionFactory.getCurrentSession();
        session.beginTransaction();
        Integer count = (Integer) session.createCriteria(persistentClass).setProjection(Projections.rowCount()).list().get(0);
        session.flush();
        session.getTransaction().commit();
        return count;
    }
}